#include "QtOpenCv.h"


QtOpenCv::QtOpenCv(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    setWindowFlags(Qt::FramelessWindowHint );//隐藏标题栏
    sendData = 0;
    //打开摄像头
    videoCap.open(0);
    //加载级联分类器
    if (faceCascade.load("D:/opencv/build/etc/haarcascades/haarcascade_frontalface_alt2.xml")) qDebug() << "级联器加载成功";
    //启动定时器
    startTimer(300);
    //定时获取连接
    checkTimer.start(5000);
    connect(&checkTimer,&QTimer::timeout,this, &QtOpenCv::timer_connect);
    //掉线补救开始定时器持续获取连接操作
    connect(&tcpSocket, &QTcpSocket::disconnected, this, &QtOpenCv::start_connect);
    connect(&tcpSocket, &QTcpSocket::connected, this, &QtOpenCv::stop_connect);//连接成功后关闭持续链接
    // 连接readyRead信号，以便读取客户端发送的数据
    connect(&tcpSocket, &QTcpSocket::readyRead, this, [this]() {QtOpenCv::onReadyRead(&tcpSocket);});
    // 创建菜单
    QMenu* menu = new QMenu(this);
    // 创建菜单项
    //设置IP地址菜单工具
    QAction* actionIP = new QAction("设置网络", this);
    // 将菜单项添加到菜单
    menu->addAction(actionIP);
    // 将菜单设置给工具按钮
    ui.toolsMenu->setMenu(menu);
    ui.toolsMenu->setPopupMode(QToolButton::InstantPopup);
    //设置工具菜单事件
    connect(actionIP, &QAction::triggered, this, &QtOpenCv::on_actionIP_triggered);
}

QtOpenCv::~QtOpenCv()
{}

//ip地址设置窗口
void QtOpenCv::on_actionIP_triggered() {
    // 创建一个对话框
    bool ok;
    ipAddresses = QInputDialog::getText(nullptr, "输入IP地址", "请输入IP地址（多个IP地址用逗号分隔）:", QLineEdit::Normal, "", &ok);
    if (ok && !ipAddresses.isEmpty()) {
        // 用户点击了OK按钮，并且输入了IP地址
        QMessageBox::information(nullptr, "输入的IP地址", "你输入的IP地址是：" + ipAddresses);

    }
    else {
        // 用户取消了输入
        QMessageBox::information(nullptr, "取消输入", "你没有输入IP地址");
    }
}

void QtOpenCv::onReadyRead(QTcpSocket* tcpSocket) {//接收数据做进一步处理
    if (tcpSocket->bytesAvailable() <= 0)return;
        QString str = QString::fromUtf8(tcpSocket->readAll());
        // 使用逗号分割字符串
        QStringList strList = str.split("\\");
        qDebug() << strList;
        IDentityTag = QString("ID:%1;姓名:%2;职务:%3").arg(strList[1], strList[0], strList[2]);
}

void QtOpenCv::checkFace(cv::Mat videoFrame){//人脸检测
    //将图片修改色度,以便检测
    Mat grayFrame;
    cvtColor(videoFrame, grayFrame,COLOR_BGR2GRAY);
    if (!grayFrame.data)return;
    //人脸检测
    std::vector<cv::Rect> faces;
    faceCascade.detectMultiScale(grayFrame, faces, 1.1, 3, 0, cv::Size(30, 30));
    if (faces.size ()> 0) {
        // 绘制矩形框
        cv::rectangle(videoFrame, faces[0], cv::Scalar(0, 255, 0), 2);
        cv::putText(videoFrame, IDentityTag.toStdString(), cv::Point(faces[0].x, faces[0].y), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 0, 0), 2);
        Mat faceData = grayFrame(cv::Rect(faces[0])).clone();
        faceCascade.detectMultiScale(grayFrame, faces, 1.1, 3, 0, cv::Size(30, 30));
        if (faces.size() <= 0)return;
        sendData += 1;
        if (sendData == 10) {
            //直接传输人脸到服务器,提取人脸
            QImage faceImage(faceData.data, faceData.cols, faceData.rows, faceData.step, QImage::Format_Grayscale8);
            //转存
            QByteArray clientSocket;
            QBuffer buffer(&clientSocket);
            faceImage.save(&buffer, "jpg");
            tcpSocket.write(clientSocket);//发送数据  
            tcpSocket.flush();
            sendData = 0;
            
        }
        cv::cvtColor(videoFrame, videoFrame, cv::COLOR_BGR2RGBA);
        QImage qImage(videoFrame.data, videoFrame.cols, videoFrame.rows, static_cast<int>(videoFrame.step), QImage::Format_RGBA8888);
        QPixmap facialDisplay = QPixmap::fromImage(qImage);
        ui.face->setPixmap(facialDisplay);
        return;
    }    
    IDentityTag = QString();
    cv::cvtColor(videoFrame, videoFrame, cv::COLOR_BGR2RGBA);
    QImage qImage(videoFrame.data, videoFrame.cols, videoFrame.rows, static_cast<int>(videoFrame.step), QImage::Format_RGBA8888);
    QPixmap facialDisplay = QPixmap::fromImage(qImage);
    ui.face->setPixmap(facialDisplay);
}
void QtOpenCv::timerEvent(QTimerEvent* e) {//捕获摄像头帧
    Mat videoFrame;
    if (videoCap.grab()) {//.grab()获取一个视频帧,并返回布尔型
        videoCap.read(videoFrame);//videoFrame获取这个帧
        if (!videoFrame.data)return;//空帧直接返回 
        QtOpenCv::checkFace(videoFrame);//调用人脸检测

    }
}
void QtOpenCv::timer_connect(){//连接服务器
    tcpSocket.connectToHost(ipAddresses,4573);
}
void QtOpenCv::start_connect(){//一旦掉线重新开启尝试连接
    //定时获取连接
    checkTimer.start(5000);
}
void QtOpenCv::stop_connect(){//一旦连接成功结束尝试链接
    //结束定时获取连接
    checkTimer.stop();
}
void QtOpenCv::on_minWidget_clicked() {//最小化窗口按钮
    this->showMinimized();

}
void QtOpenCv::on_restoreWidget_clicked(){//调整窗口大小
    if (this->isMaximized()){
        this->showNormal(); // 原大小窗口
    }else {
        this->showMaximized(); // 最大化窗口
    }
}
void QtOpenCv::on_quitApp_clicked(){//关闭程序
    videoCap.release();
    // 关闭窗口
    disconnect(&tcpSocket, &QTcpSocket::disconnected, this, &QtOpenCv::start_connect);//不在允许重启
    close();
}

//窗口重构---------------------------------------------------------------------------
//跟随窗口大小调整窗口组件位置
void QtOpenCv::resizeEvent(QResizeEvent* event) {
    int width = this->size().width();// 获取窗口的新大小
    int height = this->size().height();
    ui.littleButtons->move(width - 90, 0);//调整标题栏窗口组件位置
    ui.face->move(90, 5 );//提示栏位置及大小调整
    ui.face->resize(4*((width-180)/4), 3 * ((height - 10) / 3));
}
//鼠标拖拽动作v
void QtOpenCv::mousePressEvent(QMouseEvent* event) {
    if (event->button() == Qt::LeftButton) {
        // 记录鼠标点击时的屏幕坐标
        dragPosition = event->globalPosition() - frameGeometry().topLeft();
        // 记录拖拽状态
        isDragging = true;
    }
    else {
        // 确保只有左键按下时才进入拖拽状态
        isDragging = false;
    }
}

void QtOpenCv::mouseMoveEvent(QMouseEvent* event) {
    if (isDragging && (event->buttons() & Qt::LeftButton)) {
        // 更新窗口位置
        move(event->globalPosition().toPoint() - dragPosition.toPoint());
    }
}

void QtOpenCv::mouseReleaseEvent(QMouseEvent* event) {
    if (event->button() == Qt::LeftButton) {
        // 鼠标左键释放，结束拖拽
        isDragging = false;
    }
}
